
#include <BPainter>
#include <BImage>
#include <BStyle>
#include <BMouseEvent>
#include <BChangeEvent>
#include <BLayout>
#include <BGroupBox>
#include <BStyle>

#include "member_BGroupBox.h"

using namespace BWE;

#define member					(*(member_BGroupBox*)_ptr)
#define member_allocate()		_ptr = new member_BGroupBox(this)
#define member_release()		delete (member_BGroupBox*)_ptr

BGroupBox::BGroupBox(BWidget* parent) : BWidget(parent)
{
	member_allocate();
	this->setPerchs(15, 30, 15, 15);
}
BGroupBox::BGroupBox(const BString& title, BWidget* parent) : BWidget(parent)
{
	member_allocate();
	this->setPerchs(15, 30, 15, 15);
	this->setTitle(title);
}
BGroupBox::~BGroupBox()
{
	member_release();
}

void BGroupBox::setAlign(Align align)
{
	if (member.align != align)
	{
		member.align = align;
		fresh();
	}
}
Align BGroupBox::align() const
{
	return ::Align_Left;
}

void BGroupBox::setCheckable(bool checkable)
{
	if (member.checkable != checkable)
	{
		member.checkable = checkable;
		member.checked = false;
		this->fresh();
	}
}
bool BGroupBox::checkable() const
{
	return member.checkable;
}

void BGroupBox::setChecked(bool checked)
{
	if (!member.checkable)
		return;
	if (member.checked != checked)
	{
		member.checked = checked;
		emit(Signal_Checked, checked);
		fresh();
	}
}
bool BGroupBox::checked() const
{
	return member.checked;
}

void BGroupBox::setFoldable(bool foldable)
{
	if (member.foldable != foldable)
	{
		member.foldable = foldable;
		member.folded = false;
		this->fresh();
	}
}
bool BGroupBox::foldable() const
{
	return member.foldable;
}

void BGroupBox::setFolded(bool folded)
{
	if (!member.foldable)
		return;
	if (member.folded != folded)
	{
		member.folded = folded;
		if (member.folded)
		{
			member.foldedMarins = this->margins();
			member.foldedMaxSize = this->maxSize();
			member.foldedPerchs = this->perchs();
			this->setMargins(0);
			this->setPerchs(0, member.foldedPerchs.top(), 0, 0);
			//this->setMaxSize(member.foldedMaxSize.width(), this->sizeHint().height());
		}
		else
		{
			this->setMargins(member.foldedMarins);
			this->setPerchs(member.foldedPerchs);
			//this->setMaxSize(member.foldedMaxSize);
		}
		emit(Signal_Folded, folded);
		this->fresh();
	}
}
bool BGroupBox::folded() const
{
	return member.folded;
}

BSize BGroupBox::sizeHint() const
{
	BSize hsize = BWidget::sizeHint();
	if (member.foldable && member.folded)
	{
		int b = this->border();
		int top = this->perch(Part_Top);
		hsize.setHeight(b + top + b);
	}
	return hsize;
}

void BGroupBox::changeEvent(const BChangeEvent& event)
{
	if (event.change() == Change_Style)
	{
		const BStyle* style = event.style();
		const BFont* font = style->font();
		if (font && this->perch(Part_Title) < font->height())
		{
			this->setPerch(Part_Title, font->height());
		}

		member.titleImage = style->image(Value_Title);

		const BValue& imageSizeValue = style->value(Value_Image_Size);
		if (imageSizeValue.valid())
			member.imageSize = imageSizeValue;

		const BValue& lineWidthValue = style->value(Value_Line_Width);
		if (lineWidthValue.valid())
			member.lineWidth = lineWidthValue;
	}
}

void BGroupBox::freshEvent(const BEvent& event)
{
	member.freshRects();
}
void BGroupBox::paintEvent(const BEvent& event)
{
	BPainter painter(this);
	painter.drawBackground();
	painter.drawClient();
	painter.drawPerch();

	if (painter.setColor(Color_Group_Line))
	{
		painter.setLineWidth(member.lineWidth);
		if (member.folded)
		{
			painter.drawLines(member.points, 2);
		}
		else
		{
			painter.drawMargin();
			painter.drawLineLoop(member.points, 4);
		}

		if (painter.setColor(Color_Perch))
		{
			painter.fillRect(member.imageRect);
		}
	}
	if (member.titleImage)
	{
		painter.drawImage(member.imageRect, member.titleImage);
	}
	else if (painter.setColor(Value_Title))
	{
		painter.fillRect(member.textRect);
	}
	if (painter.setColor(Color_Text))
	{
		if (member.t_title.size())
			painter.drawText(member.textRect, member.t_title);
		else
			painter.drawText(member.textRect, this->title());
	}
	painter.drawMargin();
	painter.drawBorder();
}

void BGroupBox::mouseClickEvent(const BMouseEvent& event)
{
	const BPoint& pos = event.pos();
	const BRect& titleRect = this->rect(Part_Title);
	if (member.checkable && titleRect.contain(pos))
	{
		this->setChecked(!member.checked);
	}
}
void BGroupBox::mouseDoubleClickEvent(const BMouseEvent& event)
{
	const BPoint& pos = event.pos();
	const BRect& titleRect = this->rect(Part_Title);
	if (member.foldable && titleRect.contain(pos))
	{
		this->setFolded(!member.folded);
	}
}
